package com.dnjn.happiness.oss.controller;

import com.dnjn.happiness.common.core.domain.KV;
import com.dnjn.happiness.common.core.utils.StringUtils;
import com.dnjn.happiness.common.cloud.controller.BaseController;
import com.dnjn.happiness.common.core.web.domain.AjaxResult;
import com.dnjn.happiness.oss.config.MinioClientConfig;
import com.dnjn.happiness.oss.config.MinioTemplate;
import com.dnjn.happiness.oss.config.ObjectItem;
import com.dnjn.happiness.oss.domain.MockMultipartFile;
import com.dnjn.happiness.common.core.utils.JsonUtils;
import com.google.common.collect.Maps;
import io.minio.MinioClient;
import io.minio.PostPolicy;
import io.minio.http.Method;
import lombok.Getter;
import lombok.Setter;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.Serializable;
import java.time.ZonedDateTime;
import java.util.Base64;
import java.util.List;
import java.util.Map;

@RestController
@Slf4j
@RequestMapping(path = {"/open/minio"})
public class OpenOssMinioController extends BaseController {

    @Autowired
    private MinioTemplate minioTemplate;

    @Autowired
    private MinioClient minioClient;
    // @Autowired  private MinioProps props;
    @Autowired
    private MinioClientConfig config;

    @GetMapping("/presignedPostFormData")
    public AjaxResult presignedPostFormData(String filename/*,@RequestParam(defaultValue = "PUT") Method method*/) {
        Map<String, String> formData = minioTemplate.getPresignedPostFormData(config.getBucketName(), filename);
        log.info("{}", JsonUtils.toJsonString(formData));

        formData.put("host", config.getDownloadDomain());
        return success(formData);
    }

    @GetMapping("/presignedPostX")
    public AjaxResult presignedPostX(String filename/*,@RequestParam(defaultValue = "PUT") Method method*/) {
        Map<String, String> formData = Maps.newHashMap();
        try {
            PostPolicy postPolicy = new PostPolicy(config.getBucketName(), ZonedDateTime.now().plusMinutes(10));
            postPolicy.addEqualsCondition("key", filename);
            Map<String, String> map = minioClient.getPresignedPostFormData(postPolicy);
            map.forEach((k, v) -> {
                //map1.put(k.replaceAll("-",""),v);
                formData.put(k, v);
            });

        } catch (Exception e) {
            log.error(e.getMessage(), e);
            throw new RuntimeException(e);
        }
        log.info("{}", JsonUtils.toJsonString(formData));
        formData.put("host", config.getDownloadDomain());
        return success(formData);
    }

    @GetMapping("/presignedUrl")//上传 图片走这个
    public AjaxResult presignedUrl(String filename/*,@RequestParam(defaultValue = "PUT") Method method*/) {
        String path = minioTemplate.getPresignedUrl(config.getBucketName(), filename, Method.PUT);
        path = path.replace(config.getEndpoint(), config.getPublishHost());
        return success(KV.by("path", path).add("url", String.format("%s/%s", config.getDownloadDomain(), filename)));
    }

    @GetMapping("/presignedUrl4Download")
    public AjaxResult presignedUrl4Download(String filename/*,@RequestParam(defaultValue = "PUT") Method method*/) {
        String path = minioTemplate.getPresignedUrl(config.getBucketName(), filename, Method.GET);
        path = path.replace(config.getEndpoint(), config.getPublishHost());
        return success(KV.by("path", path));
    }

    //    @GetMapping("/listObjectName")
    public AjaxResult listObject() throws Exception {
        List<ObjectItem> items = minioTemplate.listObjects(config.getBucketName(), null);
        items.forEach(it -> it.setUrl(StringUtils.format("{}/{}/{}", config.getPublishHost(), config.getBucketName(), it.getObjectName())));
        return success(items);
    }

    //    @PostMapping("/upload")
    public AjaxResult upload(@RequestPart("file") MultipartFile file, @RequestParam(defaultValue = "images") String prefix) {
        List<String> upload = minioTemplate.upload(config.getBucketName(), prefix, new MultipartFile[]{file});
        //String path = config.getPublishHost() + "/" + config.getBucketName() + "/" + upload.get(0);
        String path = StringUtils.format("{}/{}/{}", config.getPublishHost(), config.getBucketName(), upload.get(0));
        return success(KV.by("path", path));
    }

    @PostMapping("/uploadBase64Image")
    public AjaxResult uploadBase64Image(@RequestBody FileVO fileVO) {
        try {
            log.info("{}",fileVO.key);
            MultipartFile multipartFile = base64toMultipartFile(fileVO);
            String key = fileVO.key;
            String path = minioTemplate.putObject(config.getBucketName(), key, multipartFile);
            path = StringUtils.format("{}{}", config.getPublishHost(), path);
            return AjaxResult.success(KV.by("path", path));
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            return AjaxResult.error(e.getMessage());
        }
    }


    private MultipartFile base64toMultipartFile(FileVO fileVO) throws IOException {
        InputStream inputStream = getByteArrayInputStream(fileVO.base64str);
        String string = fileVO.key;
        MultipartFile file = new MockMultipartFile(string, string, fileVO.getMediaType(), inputStream);
        inputStream.close();
        return file;
    }

    private InputStream getByteArrayInputStream(String imageaddr) {
        // 去掉base64前缀 data:image/jpeg;base64,
        imageaddr = imageaddr.substring(imageaddr.indexOf(",", 1) + 1, imageaddr.length());
        // 解密
        // Base64.Decoder decoder = Base64.getDecoder();
        Base64.Decoder decoder = Base64.getMimeDecoder();
        // 去掉base64前缀 data:image/jpeg;base64,
        byte[] b = decoder.decode(imageaddr);
        // 处理数据
        for (int j = 0; j < b.length; ++j) {
            if (b[j] < 0) {
                b[j] += 256;
            }
        }
        return new ByteArrayInputStream(b);
    }


    @Getter
    @Setter
    public static class FileVO implements Serializable {
        protected String base64str;
        protected String filename;
        protected String key;
        //protected String mediaType; //image/jpeg,  image/png

        public String getMediaType() {
            return base64str.split(";")[0].substring(5);
        }
    }
}

